home *** CD-ROM | disk | FTP | other *** search
- /* File v_maccur.c:
- * Machine specific part of curses implementation for Macintosh.
- * Also includes rudimentary replacements for stdio functions.
- *
- * Copyright (c) 1994
- * by Robert Zimmerman
- *
- * This code may be included in any work, public or private, with the
- * exception of creating a commercial curses-compatible subroutine
- * library. (In other words, use the code all you want, but please don't
- * rip off the author by reselling this code as your own).
- *
- */
-
- #include <AppleEvents.h>
- #include <limits.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <string.h>
- #include <signal.h>
- #include "curses.h"
-
- /****
- * Resources expected by this code are:
- * An ALRT and DITL to put up alerts with the function maccur_cpu_share (see macro ALERT_RSRC_ID).
- * A MENU and MBAR to draw the menu (which includes only the apple menu) (see macro MENU_RES_ID).
- *
- * Optionally, an ALRT and DITL for the "About x..." menu item (see variable _maccur_about_res_id).
- ****/
-
- /****
- * First some macros for font, screen setup, etc:
- ****/
-
- #define X_MARGIN 2
- #define Y_MARGIN 4
- #define Y_PIX_WIN (rowheight_pix * _maccur_lines + Y_MARGIN)
- #define X_PIX_WIN (charwid_pix * _maccur_cols + 2 * X_MARGIN)
-
- /****
- * ROW/COL_TO_PIX determine pen position to write character at row/col.
- * First row/column is 0/0.
- ****/
-
- #define COL_TO_PIX(col) ((col) * charwid_pix + X_MARGIN)
- #define ROW_TO_PIX(row) (((row) + 1) * rowheight_pix)
-
- #define MAX_OUT_STRSEG 132 /* Max number of parts of a single character row (distinguished by writing attrib. */
- #define MAX_TYPEAHEAD 32 /* Number of keystrokes that will be buffered. */
- #define FLASH_TICKS 8 /* Flash cursor 2x second. */
- #define WINDO_TOP_ON_SCREEN 40 /* Default position of window on screen. */
- #define WINDO_LEFT_ON_SCREEN 5
- #define ALERT_RSRC_ID 128 /* ALRT id for generalize alert. */
- #define MENU_RES_ID 128 /* MBAR id for putting up (not much of a) menu. */
-
- #define TST_BIT(i, b) ((i) & (1 << (b)))
- #define SET_BIT(b) (1 << (b))
-
- enum {
- MACCUR_RETURN_ON_IDLE_BIT,
- MACCUR_RETURN_ON_CHAR_BIT
- };
-
- typedef struct key_evnt_strct { /* Struct in which to buffer keyboard events. */
- long msg;
- short mod;
- } KEY_EVENT;
-
- static KEY_EVENT typebuf[MAX_TYPEAHEAD]; /* Buffer for keyboard events. */
-
- /****
- * The following can be modified before curses is initialized
- * in order to customize display, etc:
- ****/
-
- int _maccur_cols = 80; /* Window will be initialized to this size. */
- int _maccur_lines = 25;
- char *_maccur_font_name = "Monaco"; /* Font to use (C string). */
- int _maccur_font_size = 9; /* Size of font. */
- int _maccur_handle_break_option = MACCUR_EXIT_ON_BREAK; /* This determines what happens on CMD-. (see enum in macurses.h). */
- int _maccur_about_res_id; /* Resource id alert to display if About... is chosen from apple menu. */
- char *_maccur_pgm_name = "Curses"; /* Program name for about and window title. */
- int _maccur_fg_sleep_ticks = 1; /* How much can WaitNextEvent sleep in foreground. */
- int _maccur_bg_sleep_ticks = 2; /* How much can WaitNextEvent sleep in background. */
- int _maccur_io_sleep_dvsr = 1; /* How many of the output calls (maccur_printf, etc) call maccur_cpu_share. */
- /* (1/_maccur_io_sleep_dvsr of output calls will call maccur_cpu_share). */
-
- static int rowheight_pix; /* Screen dimensions for each character. */
- static int charwid_pix;
- static short font_num; /* Writing font number. */
- static short font_res_id; /* Font resource ID. */
- static int show_cursor_flag; /* TRUE if cursor should be flashed. */
- static Rect cursor_rect; /* Cursor, as a Rect. */
- static WindowPtr the_windo; /* Program window. */
- static long last_flash_when; /* Keep track of when cursor flashed. */
- static int in_background_flag; /* Keep track of program foreground/bkground state. */
- static int cursor_inverted; /* True if cursor is currently inverted. */
- static int typeahead_cnt; /* How many characters are waiting in typebuf. */
- static int typeahead_indx; /* Where does next character go in typebuf. */
- static int outchar_indx; /* Where does next character come out of typebuf. */
- static chtype *screen_char_arry; /* Array holding screen contents. */
- static FontInfo fnt_info; /* Description of writing font. */
- static int maccur_about_mitm; /* 1 if there is an About... item in apple menu. */
- static int maccur_has_menu; /* True if MBAR resource was found and menu put up. */
-
- static int direct_curs_pos_row; /* Keep track of cursor position when in direct (non-curses) mode. */
- static int direct_curs_pos_col;
-
- static int cpu_share_rot_cnt; /* When this reaches _maccur_io_sleep_dvsr its time to share CPU. */
-
- /********
- **
- ** maccur_init_toolbox: Initialize mac stuff.
- **
- **
- ********/
-
- static void maccur_init_toolbox(void)
- {
- InitGraf(&thePort);
- InitFonts();
- FlushEvents(everyEvent, 0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor();
- MaxApplZone();
- }
-
- /********
- **
- ** event_do_nothing: Do nothing in response to apple events.
- **
- **
- ********/
-
- static pascal OSErr event_do_nothing(
- const AppleEvent *theAppleEvent,
- AppleEvent *reply,
- long refCon
- ) {
- return 0;
- }
-
- /********
- **
- ** quit_app: Quit application in response to apple event.
- ** This is fairly severe -- Should put up a dialogue box?
- **
- **
- ********/
-
- static pascal OSErr quit_app(
- const AppleEvent *theAppleEvent,
- AppleEvent *reply,
- long refCon
- ) {
- ExitToShell();
- return 0;
- }
-
- /********
- **
- ** maccur_init_event: Initialize handlers (such as they are) for
- ** required apple events.
- **
- **
- ********/
-
- static void maccur_init_event(void)
- {
- AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- event_do_nothing, 0L, FALSE);
- AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- event_do_nothing, 0L, FALSE);
- AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
- event_do_nothing, 0L, FALSE);
- AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- quit_app, 0L, FALSE);
- }
-
- /********
- **
- ** maccur_get_font_info: Search for resouce for desired font via FOND resource.
- ** Return dimension of characters for sizing of window. There must be an
- ** easier way to determine the required window size b4 putting the window
- ** up (and without putting a fixed size window in resource file).
- **
- ** Returns:
- ** TRUE if font resource found, else FALSE.
- **
- **
- ********/
-
- static int maccur_get_font_info(
- char *font_name, /* -R- Name of desired font. */
- int font_pts, /* -R- Size of desired font. */
- short *font_num_ptr, /* -W- Return font number. */
- short *font_id_ptr, /* -W- Return font resource id. */
- int *rowheight_pix_ptr, /* -W- Return height of font. */
- int *charwid_pix_ptr /* -W- Return width of font. */
- ) {
- ResType res_typ;
- Handle rsrc_ptr;
- FamRec *fnt_fam_ptr;
- FontAssoc *fnt_cnt_ptr;
- AsscEntry *fnt_assc_list_ptr;
- FontRec *fnt_rec_ptr;
- int i;
- char buf[256];
-
- memcpy(&res_typ, "FOND", sizeof(res_typ));
- if ((rsrc_ptr = GetNamedResource(res_typ, (ConstStr255Param) font_name)) == NULL)
- return FALSE;
-
- GetResInfo(rsrc_ptr, font_id_ptr, &res_typ, (unsigned char *) buf);
- if (ResError() != noErr) return FALSE;
-
- fnt_fam_ptr = *((FamRec **)rsrc_ptr);
- fnt_cnt_ptr = (FontAssoc *)(fnt_fam_ptr + 1);
- fnt_assc_list_ptr = (AsscEntry *)(fnt_cnt_ptr + 1);
-
- *font_num_ptr = fnt_fam_ptr->ffFamID;
-
- for (i = 0; i < fnt_cnt_ptr->numAssoc + 1; i++)
- {
- if ((fnt_assc_list_ptr + i)->fontSize == font_pts &&
- (fnt_assc_list_ptr + i)->fontStyle == 0)
- break;
- }
-
- if (i == fnt_cnt_ptr->numAssoc + 1) return FALSE;
-
- fnt_rec_ptr = NULL;
- if ((fnt_assc_list_ptr + i)->fontID == *font_id_ptr * 128 + font_pts)
- {
- memcpy(&res_typ, "FONT", sizeof(res_typ));
- if ((rsrc_ptr = GetResource(res_typ, *font_id_ptr)) != NULL)
- fnt_rec_ptr = *((FontRec **)rsrc_ptr);
- }
-
- if (fnt_rec_ptr != NULL)
- {
- memcpy(&res_typ, "NFNT", sizeof(res_typ));
- if ((rsrc_ptr = GetResource(res_typ, *font_id_ptr)) != NULL)
- fnt_rec_ptr = *((FontRec **)rsrc_ptr);
- }
-
- if (fnt_rec_ptr == NULL) return FALSE;
-
- *rowheight_pix_ptr = fnt_rec_ptr->fRectHeight;
- *charwid_pix_ptr = fnt_rec_ptr->fRectWidth;
-
- return TRUE;
- }
-
- /********
- **
- ** maccur_init_window: Size and open curses window.
- **
- **
- ********/
-
- static void maccur_init_window(void)
- {
- Rect windo_rect;
- ResType font_res;
- FontRec *fnt_rec_ptr;
- Handle rsrc_ptr;
- char windo_titl[128], font_name[32];
-
- font_name[0] = strlen(_maccur_font_name); /* Copy font name to local pascal string. */
- strcpy(font_name + 1, _maccur_font_name);
-
- if (_maccur_font_size <= 0) _maccur_font_size = 9; /* Make sure font size is reasonable. */
-
- windo_rect.top = WINDO_TOP_ON_SCREEN;
- windo_rect.left = WINDO_LEFT_ON_SCREEN;
- if (maccur_get_font_info(font_name, _maccur_font_size, /* Try to find font dimensions before putting up window. */
- &font_num, &font_res_id,
- &rowheight_pix, &charwid_pix))
- {
- windo_rect.bottom = windo_rect.top + Y_PIX_WIN;
- windo_rect.right = windo_rect.left + X_PIX_WIN;
- }
- else
- {
- GetFNum((ConstStr255Param) font_name, &font_num); /* If can't find them, put it up and then resize it. */
- if (font_num == 0)
- {
- maccur_alert_msg("Could not access font '%s'!",
- _maccur_font_name);
- ExitToShell();
- }
- windo_rect.bottom = windo_rect.top + 10;
- windo_rect.right = windo_rect.left + 10;
- }
-
- strcpy(windo_titl, (_maccur_pgm_name == NULL ||
- *_maccur_pgm_name == '\0') ?
- "Curses" : _maccur_pgm_name);
- if ((the_windo = NewWindow(nil, &windo_rect,
- CtoPstr(windo_titl), TRUE,
- noGrowDocProc, (WindowPtr)-1L,
- FALSE, (long)nil)) == nil)
- {
- maccur_alert_msg("Could not initialize program window!");
- ExitToShell();
- }
-
- SetPort(the_windo);
-
- if (font_num != 0)
- TextFont(font_num);
-
- TextSize(_maccur_font_size);
- GetFontInfo(&fnt_info);
- if (charwid_pix != fnt_info.widMax ||
- rowheight_pix != fnt_info.ascent + fnt_info.descent + fnt_info.leading)
- {
- charwid_pix = fnt_info.widMax;
- rowheight_pix = fnt_info.ascent + fnt_info.descent + fnt_info.leading;
- SizeWindow(the_windo, X_PIX_WIN, Y_PIX_WIN, TRUE);
- }
-
- /* Could check if bold-condense is same size as normal to allow/dissallow bold mode? */
- ShowWindow(the_windo);
- }
-
- /********
- **
- ** maccur_init_menus: Set up menu bar (for now, only the apple menu).
- **
- **
- ********/
-
- static void maccur_init_menus(void)
- {
- Handle menu_bar_hndl;
- MenuHandle menu_hndl;
- char about_str[128];
-
- if ((menu_bar_hndl = GetNewMBar(MENU_RES_ID)) != NULL)
- {
- SetMenuBar(menu_bar_hndl);
- menu_hndl = GetMHandle(MENU_RES_ID);
- if (_maccur_about_res_id != 0)
- {
- sprintf(about_str, "About %s...", _maccur_pgm_name);
- SetItem(menu_hndl, 1, CtoPstr(about_str));
- maccur_about_mitm = 1;
- }
- else
- {
- DelMenuItem(menu_hndl, 1);
- maccur_about_mitm = 0;
- }
- AddResMenu(menu_hndl, 'DRVR');
-
- DrawMenuBar();
- maccur_has_menu = TRUE;
- }
- else maccur_has_menu = FALSE;
- }
-
- /********
- **
- ** maccur_draw_text_line: Write a single line of text to window. Input text is
- ** type chtype, with attribute info.
- **
- **
- ********/
-
- static void maccur_draw_text_line(
- chtype *line_ptr, /* -R- Pointer to text to write. */
- int n, /* -R- Number of characters. */
- int row, /* -R- Start at what row on screen (first row is 0). */
- int col /* -R- Start at what column on screen (first col is 0). */
- ) {
- int i, first_pass_flag, j, attr, previous_attr, txt_face;
- char out_str[MAX_OUT_STRSEG];
-
- SetPort(the_windo);
-
- MoveTo(COL_TO_PIX(col), ROW_TO_PIX(row));
-
- for (i = 0, first_pass_flag = TRUE; i < n; ) /* Loop until string is written, writing it in segments */
- { /* that all have the same attribute. */
- for (j = 0, attr = (*(line_ptr + i) & A_ATTRIBUTES);
- i < n && j < MAX_OUT_STRSEG && attr == (*(line_ptr + i) & A_ATTRIBUTES);
- i++, j++)
- out_str[j] = (*(line_ptr + i) & A_CHARTEXT);
-
- if (attr != previous_attr || first_pass_flag) /* Determine/set attribute for this segment... */
- {
- if (attr & A_REVERSE || attr & A_STANDOUT) /* Should do standout w/ hilite? */
- TextMode(notSrcCopy);
- else
- TextMode(srcCopy);
-
- txt_face = normal;
- if (attr & A_UNDERLINE)
- txt_face |= underline;
-
- if (attr & A_BOLD) /* It is assument that bold condense is same size as normal. */
- txt_face |= (bold | condense);
-
- TextFace(txt_face);
- previous_attr = attr;
- }
- DrawText(out_str, 0, j);
- first_pass_flag = FALSE;
- }
- }
-
- /********
- **
- ** maccur_flash_cursor: Flash cursor.
- **
- **
- ********/
-
- static void maccur_flash_cursor(void)
- {
- InvertRect(&cursor_rect);
- cursor_inverted = !cursor_inverted;
- }
-
- /********
- **
- ** maccur_unflash_cursor: Unhighlight cursor if it is highlighted.
- **
- **
- ********/
-
- static void maccur_unflash_cursor(void)
- {
- if (cursor_inverted) maccur_flash_cursor();
- }
-
- /********
- **
- ** maccur_set_cursor: Set cursor_rect to reflect current cursor position.
- ** Before moving it, un-invert it if necessary (based on cursor_inverted flag).
- **
- **
- ********/
-
- static void maccur_set_cursor(
- int row, /* -R- Row for cursor. */
- int col /* -R- Column for cursor. */
- ) {
-
- if (cursor_inverted) maccur_flash_cursor();
- show_cursor_flag = TRUE;
-
- row = MIN(row, _maccur_lines - 1);
- col = MIN(col, _maccur_cols - 1);
-
- cursor_rect.bottom = ROW_TO_PIX(row) + fnt_info.descent + fnt_info.leading;
- cursor_rect.right = COL_TO_PIX(col + 1);
- cursor_rect.top = cursor_rect.bottom - rowheight_pix;
- cursor_rect.left = COL_TO_PIX(col);
-
- }
-
- /********
- **
- ** maccur_mouse_down_evnt: Do something about mouse down event. All that
- ** is handled is the apple menu, dragging the window, and system clicks.
- **
- **
- ********/
-
- static void maccur_mouse_down_evnt(
- EventRecord *event_ptr /* -R- The event details. */
- ) {
- WindowPtr wndo_ptr;
- MenuHandle apl_menu_hndl;
- Str255 nam;
- long menu_choice;
- short wnd_part, menu_id, menu_itm, num;
-
- wnd_part = FindWindow(event_ptr->where, &wndo_ptr);
- switch (wnd_part)
- {
- case inMenuBar:
- if ((menu_choice = MenuSelect(event_ptr->where)) != 0)
- {
- menu_id = HiWord(menu_choice);
- menu_itm = LoWord(menu_choice);
-
- if (menu_id == MENU_RES_ID)
- {
- if (menu_itm == maccur_about_mitm) /* See if this is about... */
- {
- if (NoteAlert(_maccur_about_res_id, NULL) == -1)
- SysBeep(1);
- }
- else
- {
- apl_menu_hndl = GetMHandle(MENU_RES_ID); /* If not, pass it on. */
- GetItem(apl_menu_hndl, menu_itm, nam);
- num = OpenDeskAcc(nam);
- }
- }
- HiliteMenu(0);
- }
- break;
-
- case inSysWindow:
- SystemClick(event_ptr, wndo_ptr);
- break;
-
- case inContent:
- break;
-
- case inDrag:
- DragWindow(wndo_ptr, event_ptr->where,
- &screenBits.bounds);
- break;
- }
- }
-
- /********
- **
- ** maccur_event_loop: Main event loop. Argument indicates whether it is to
- ** return due to a null event or due to a key stroke.
- **
- ** Returns:
- ** Reason for return (null or keystroke).
- **
- **
- ********/
-
- static int maccur_event_loop(
- int until_flags
- ) {
- EventRecord event;
- int i;
- long sleep;
- char c;
-
- if (TST_BIT(until_flags, MACCUR_RETURN_ON_CHAR_BIT)) /* If waiting for a character, don't need a lot of CPU. */
- {
- if (in_background_flag) /* Don't need any in background. */
- sleep = LONG_MAX;
- else sleep = FLASH_TICKS; /* Just need enough to flash cursor in foreground. */
- }
- else /* If not waiting for a character, try to give up some time. */
- { /* but maybe not a lot. */
- if (in_background_flag)
- sleep = _maccur_bg_sleep_ticks;
- else sleep = _maccur_fg_sleep_ticks;
- }
-
- while (1) /* Loop until return condition is met. */
- {
- if (WaitNextEvent(everyEvent, &event, sleep, nil))
- {
- switch (event.what)
- {
- case kHighLevelEvent:
- AEProcessAppleEvent(&event);
- break;
-
- case mouseDown:
- if (maccur_has_menu)
- maccur_mouse_down_evnt(&event);
- break;
-
- case keyDown:
- case autoKey:
- if ((event.modifiers & cmdKey) != 0) /* Ignore all command keys except CMD-. */
- {
- if ((event.message & charCodeMask) == '.') /* This may exit right away or simulate a control-C interrupt. */
- {
- switch (_maccur_handle_break_option)
- {
- case MACCUR_EXIT_ON_BREAK:
- ExitToShell();
- break;
-
- case MACCUR_SIGNAL_BREAK:
- raise(SIGINT);
- break;
- }
- }
- else break;
- }
-
- if (typeahead_cnt >= MAX_TYPEAHEAD) /* Other keystrokes go into typeahead (if there is room). */
- SysBeep(1); /* Typeahead buf is circular. */
- else
- {
- typebuf[typeahead_indx % MAX_TYPEAHEAD].msg = event.message;
- typebuf[typeahead_indx % MAX_TYPEAHEAD].mod = event.modifiers;
- }
- typeahead_indx++;
- typeahead_cnt++;
-
- if (TST_BIT(until_flags, MACCUR_RETURN_ON_CHAR_BIT))/* Return if keystroke was what was wanted. */
- return MACCUR_RETURN_ON_CHAR_BIT;
- break;
-
- case updateEvt:
- BeginUpdate((WindowPtr)(event.message));
-
- EraseRect(&cursor_rect); /* This may be unnecessary??? */
- for (i = 0; i < _maccur_lines; i++) /* Redraw the screen. */
- maccur_draw_text_line(screen_char_arry + i * _maccur_cols,
- _maccur_cols, i, 0);
- cursor_inverted = FALSE;
-
- EndUpdate((WindowPtr)(event.message));
- break;
-
- case osEvt: /* Switch background/foreground. */
- if ((event.message & suspendResumeMessage) == resumeFlag)
- in_background_flag = FALSE;
- else
- {
- in_background_flag = TRUE;
- maccur_unflash_cursor(); /* Turn cursor off in the background. */
- }
- break;
-
- }
- }
- else if (TST_BIT(until_flags, MACCUR_RETURN_ON_IDLE_BIT)) /* If just letting CPU run, this is the cue to split. */
- return MACCUR_RETURN_ON_IDLE_BIT;
-
- if (!in_background_flag && show_cursor_flag && /* See if its time to flash the cursor. */
- event.when - last_flash_when > FLASH_TICKS)
- {
- if (event.what != osEvt)
- maccur_flash_cursor();
- last_flash_when = event.when;
- }
- }
- }
-
- /****
- * The following "keypad map" maps various non-ascii keystrokes to
- * their curses KEY_xxx equivalents. This could be made global so
- * that user supplied replacements could be linked in (but who would
- * want to go to all that trouble).
- ****/
-
- #define KEYMAP_BASE 0x33 /* Key number of first key to translate. */
- #define KEYMAP_TOP (KEYMAP_BASE + sizeof(dflt_keypad_map)/sizeof(KEYPAD_MAP))
- #define KEYMAP_NOCODE 0 /* If this is key translation, return ascii code for that key. */
-
- typedef struct keypad_map_strct { /* Determine what to do with key/modifier: */
- chtype basic_code; /* This is translation of unmodified key. */
- chtype shift_code; /* Translation of key with shift. */
- chtype opt_code; /* Translation of key with option. */
- chtype shift_opt_code; /* Translation of key with shift-option. */
- } KEYPAD_MAP;
-
- static KEYPAD_MAP dflt_keypad_map[] = {
- /* 33 delete */ {KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE, KEY_BACKSPACE},
- /* 34 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 35 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 36 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 37 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 38 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 39 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 3A */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 3B */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 3C */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 3D */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 3E */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 3F */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 40 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 41 KP-. */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 42 rt arrow (Mac +) */ {KEY_RIGHT, KEY_SRIGHT, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 43 KP-* */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 44 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 45 KP-+ */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 46 left arrow (Mac +) */ {KEY_LEFT, KEY_SLEFT, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 47 clear */ {KEY_CLEAR, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 48 down arrow (Mac +) */ {KEY_DOWN, KEY_NPAGE, KEY_END, KEYMAP_NOCODE},
- /* 49 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 4A */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 4B KP-/ */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 4C enter */ {KEY_ENTER, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 4D up arrow (Mac +) */ {KEY_UP, KEY_PPAGE, KEY_HOME, KEYMAP_NOCODE},
- /* 4E KP-- */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 4F */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 50 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 51 KP-= */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 52 KP-0 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEY_F(0), KEY_F(10)},
- /* 53 KP-1 */ {KEY_C1, KEYMAP_NOCODE, KEY_F(1), KEY_F(11)},
- /* 54 KP-2 */ {KEY_DOWN, KEYMAP_NOCODE, KEY_F(2), KEY_F(12)},
- /* 55 KP-3 */ {KEY_C3, KEYMAP_NOCODE, KEY_F(3), KEY_F(13)},
- /* 56 KP-4 */ {KEY_LEFT, KEYMAP_NOCODE, KEY_F(4), KEY_F(14)},
- /* 57 KP-5 */ {KEY_B2, KEYMAP_NOCODE, KEY_F(5), KEY_F(15)},
- /* 58 KP-6 */ {KEY_RIGHT, KEYMAP_NOCODE, KEY_F(6), KEY_F(16)},
- /* 59 KP-7 */ {KEY_A1, KEYMAP_NOCODE, KEY_F(7), KEY_F(17)},
- /* 5A */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 5B KP-8 */ {KEY_UP, KEYMAP_NOCODE, KEY_F(8), KEY_F(18)},
- /* 5C KP-9 */ {KEY_A3, KEYMAP_NOCODE, KEY_F(9), KEY_F(19)},
- /* 5D */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 5E */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 5F */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 60 F5 */ {KEY_F(5), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 61 F6 */ {KEY_F(6), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 62 F7 */ {KEY_F(7), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 63 F3 */ {KEY_F(3), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 64 F8 */ {KEY_F(8), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 65 F9 */ {KEY_F(9), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 66 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 67 F11 */ {KEY_F(11), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 68 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 69 F13 */ {KEY_F(13), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 6A */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 6B F14 */ {KEY_F(14), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 6C */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 6D F10 */ {KEY_F(10), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 6E */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 6F F12 */ {KEY_F(12), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 70 */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 71 F15 */ {KEY_F(15), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 72 ins */ {KEY_IC, KEY_IL, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 73 home */ {KEY_HOME, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 74 pgup */ {KEY_PPAGE, KEY_SR, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 75 fwd del */ {KEY_DC, KEY_DL, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 76 F4 */ {KEY_F(4), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 77 end */ {KEY_END, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 78 F2 */ {KEY_F(2), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 79 pgdn */ {KEY_NPAGE, KEY_SF, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 7A F1 */ {KEY_F(1), KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 7B left arrow */ {KEY_LEFT, KEY_SLEFT, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 7C rt arrow */ {KEY_RIGHT, KEY_SRIGHT, KEYMAP_NOCODE, KEYMAP_NOCODE},
- /* 7D down arrow */ {KEY_DOWN, KEY_NPAGE, KEY_END, KEYMAP_NOCODE},
- /* 7E up arrow */ {KEY_UP, KEY_PPAGE, KEY_HOME, KEYMAP_NOCODE},
- /* 7F */ {KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE, KEYMAP_NOCODE}
- };
-
- /********
- **
- ** maccur_key_trans: Return curses key code based on keystroke event.
- ** If key has no entry in translation table, or entry is KEYMAP_NOCODE,
- ** return ascii value.
- **
- ** Returns:
- ** Character translation of keystroke (type chtype).
- **
- **
- ********/
-
- static chtype maccur_key_trans(
- KEY_EVENT *ch_evnt_ptr,
- int keypad_enabled_flag
- ) {
- chtype c, c_ascii, key;
-
- c_ascii = ch_evnt_ptr->msg & charCodeMask;
- key = (ch_evnt_ptr->msg & keyCodeMask) >> 8;
-
- if (keypad_enabled_flag && key >= KEYMAP_BASE && key < KEYMAP_TOP)
- {
- if ((ch_evnt_ptr->mod & shiftKey) && (ch_evnt_ptr->mod & optionKey))
- c = (dflt_keypad_map + (key - KEYMAP_BASE))->shift_opt_code;
- else if ((ch_evnt_ptr->mod & shiftKey))
- c = (dflt_keypad_map + (key - KEYMAP_BASE))->shift_code;
- else if ((ch_evnt_ptr->mod & optionKey))
- c = (dflt_keypad_map + (key - KEYMAP_BASE))->opt_code;
- else
- c = (dflt_keypad_map + (key - KEYMAP_BASE))->basic_code;
-
- if (c == KEYMAP_NOCODE) c = c_ascii;
- }
- else
- {
- if (key == 0x4C) c = '\n'; /* Give the keypad enter key a better ascii translation. */
- else c = c_ascii;
- }
-
- return c;
- }
-
- /********
- **
- ** maccur_flush_typeahead: Flush the typeahead buffer.
- **
- **
- ********/
-
- void maccur_flush_typeahead(
- void
- ) {
-
- typeahead_indx = typeahead_cnt = outchar_indx = 0;
- }
-
- /********
- **
- ** maccur_init: Entry point for initalization. Sets LINES and COLS
- ** to the size of the window that is opened up.
- **
- ** Returns:
- ** TRUE if initialization is successful, else FALSE.
- **
- **
- ********/
-
- bool maccur_init(void)
- {
- int i, screen_chars;
-
- screen_chars = _maccur_cols * _maccur_lines;
- if (screen_char_arry == NULL) /* Allow for multiple calls to this routine (especially */
- { /* implicit ones for fake stdio). */
- maccur_init_toolbox();
- maccur_init_event();
- maccur_init_window();
- maccur_init_menus();
-
- LINES = _maccur_lines;
- COLS = _maccur_cols;
-
- if ((screen_char_arry = malloc(screen_chars * sizeof(chtype))) == NULL)
- return FALSE;
- }
-
- for (i = 0; i < screen_chars; i++) /* Blank the screen. */
- *(screen_char_arry + i) = ' ';
-
- return TRUE;
- }
-
- /********
- **
- ** maccur_refresh: Refresh the screen for a curses window.
- **
- ** Returns:
- ** ERR on error, else OK.
- **
- **
- ********/
-
- int maccur_refresh(WINDOW *win, bool outflag)
- {
- static int next_cursor_col = 0; /* Save cursor position for next window refresh. */
- static int next_cursor_row = 0; /* (in case there are multiple calls before refresh and some have leaveok TRUE). */
- static int window_current_flag; /* Set to true when window is updated from saved image. */
- static int cursor_enabled_flag; /* Set to true if at least one window contributing to screen has a cursor. */
- int i, mov_size, maxx, maxy;
- chtype *src_ptr, *dst_ptr;
- /* Your comment here */
-
- if (screen_char_arry == NULL) return ERR; /* Initialization has not been done (bad). */
-
- if (win) /* If window was passed, transfer chars from it. */
- {
- if (win->_begy < _maccur_lines && win->_begx < _maccur_cols)
- {
- dst_ptr = screen_char_arry + (win->_begy * _maccur_cols) +
- win->_begx;
- if (win->_flags & _ISPAD)
- {
- maxx = win->_pmap_maxx - win->_pmap_orgx; /* For pads, get # rows and columns to display. */
- maxy = win->_pmap_maxy - win->_pmap_orgy;
- src_ptr = win->_y + /* Point to 1st displayed character in pad. */
- ((win->_pmap_orgy * win->_xdim) +
- win->_pmap_orgx);
- }
- else
- {
- maxx = win->_maxx;
- maxy = win->_maxy;
- src_ptr = win->_y;
- }
- mov_size = MIN(maxx, _maccur_cols - win->_begx) *
- sizeof(chtype);
- for (i = 0; i < maxy && i + win->_begy < _maccur_lines; /* Copy text from window to screen image. */
- i++, dst_ptr += _maccur_cols,
- src_ptr += win->_xdim)
- memcpy(dst_ptr, src_ptr, mov_size);
- }
-
- if (!win->_leave) /* If cursor is not left off, */
- {
- next_cursor_row = _CURS_CURSOR_SCREEN_ROW(win); /* Save its position. */
- next_cursor_col = _CURS_CURSOR_SCREEN_COL(win);
- cursor_enabled_flag = TRUE; /* It will be enabled on next screen update. */
- }
- else if (window_current_flag) /* If this is 1st refresh after update and cursor */
- cursor_enabled_flag = FALSE; /* disabled, indicate that. Subsequent refreshes */
- else cursor_enabled_flag = cursor_enabled_flag || FALSE; /* or into flag so if cursor is enabled once it is shown. */
- window_current_flag = FALSE;
- }
-
- if (outflag) /* If actual screen update is to be done... */
- {
- for (i = 0; i < _maccur_lines; i++) /* Draw the characters. */
- maccur_draw_text_line(screen_char_arry + i * _maccur_cols,
- _maccur_cols, i, 0);
- if (cursor_enabled_flag)
- {
- cursor_inverted = FALSE; /* Window was completely re-written, so cursor is gone. */
- maccur_set_cursor(next_cursor_row, next_cursor_col);
- }
- else show_cursor_flag = FALSE;
- window_current_flag = TRUE;
- }
-
- return OK;
- }
-
- /********
- **
- ** maccur_end: Exit curses mode.
- **
- ** Returns:
- ** OK.
- **
- **
- ********/
-
- bool maccur_end(void)
- {
- void maccur_noncurse_mode_scroll();
-
- maccur_noncurse_mode_scroll(); /* Scroll screen up a line and position cursor at bottom. */
-
- direct_curs_pos_row = _maccur_lines - 1;
- direct_curs_pos_col = 0;
-
- maccur_set_cursor(direct_curs_pos_row, direct_curs_pos_col);
- return OK;
- }
-
- /********
- **
- ** maccur_beep: Beep or flash the screen.
- **
- **
- ********/
-
- void maccur_beep(
- int flash_flag /* -R- TRUE to flash instead of beep. */
- ) {
- if (flash_flag)
- SysBeep(0);
- else
- SysBeep(1);
- }
-
- /********
- **
- ** maccur_kbinp: Take a single character input.
- **
- ** Returns:
- ** Character read, or ERR if no character ready or error.
- **
- **
- ********/
-
- int maccur_kbinp(WINDOW *win, bool raw, bool cbreak)
- {
-
- if (typeahead_cnt == 0 && win->_nodelay) /* If caller is in a hurry don't make 'em wait */
- return ERR;
-
- if (typeahead_cnt == 0) /* If need to wait for input... */
- {
- maccur_set_cursor(_CURS_CURSOR_SCREEN_ROW(win), /* Set cursor to current input position. */
- _CURS_CURSOR_SCREEN_COL(win)); /* (this will also un-invert it). */
- if (win->_leave) /* If cursor is to be left off, set flag to false. */
- show_cursor_flag = FALSE;
- maccur_event_loop(SET_BIT(MACCUR_RETURN_ON_CHAR_BIT));
- }
-
- if (typeahead_cnt > 0) /* There should be something to return now, so do it... */
- {
- typeahead_cnt--;
- if (outchar_indx >= MAX_TYPEAHEAD) outchar_indx = 0;
- return maccur_key_trans(typebuf + outchar_indx++, win->_use_keypad);
- }
-
- return ERR;
- }
-
- /********
- **
- ** maccur_alert_text: Display a string in an alert box.
- ** Trim white space and newlines from beginning and end of string first.
- **
- **
- ********/
-
- static void maccur_alert_text(
- char *txt
- ) {
- static char buf[256];
- int len;
-
- while (isspace(*txt)) /* Strip off leading white space. */
- txt++;
- len = strlen(txt);
-
- while (len > 0 && isspace(*(txt + len - 1))) /* Strip off trailing white space. */
- len--;
- if (len > 255) len = 255;
-
- buf[0] = len; /* Make it a pascal string. */
- memcpy(buf + 1, txt, len);
-
- ParamText((ConstStr255Param) buf, NULL, NULL, NULL);
-
- Alert(ALERT_RSRC_ID, NULL); /* Display as an alert. */
- }
-
- /********
- **
- ** maccur_alert_msg: Display a string as an alert message, after
- ** formatting it with sprintf.
- **
- **
- ********/
-
- void maccur_alert_msg(
- char *fmt,
- ...
- ) {
- va_list args;
- int rtn;
-
- if (screen_char_arry == NULL)
- maccur_init();
-
- va_start(args, fmt);
- rtn = vsprintf(_curses_prntw, fmt, args);
- va_end(args);
-
- if (rtn < 0) strcpy(_curses_prntw, "Error in curses");
-
- maccur_alert_text(_curses_prntw);
- }
-
- /********
- **
- ** maccur_cpu_share: Call the event manager so CPU time can be shared.
- **
- **
- ********/
-
- void maccur_cpu_share(void)
- {
- maccur_event_loop(SET_BIT(MACCUR_RETURN_ON_IDLE_BIT));
- }
-
-
- /* ************************************************************************** */
- /* STDIO emulation */
- /* */
- /* The following routines can be used to emulate standard io calls to stdin */
- /* and stdout, placing the output in the curses window. */
- /* */
- /* ************************************************************************** */
-
-
- /********
- **
- ** maccur_noncurse_mode_scroll: Scroll the screen up a line.
- **
- **
- ********/
-
- static void maccur_noncurse_mode_scroll(void)
- {
- int i;
- chtype *scrn_ptr;
-
- memmove(screen_char_arry, screen_char_arry + _maccur_cols, /* Scroll it up. */
- _maccur_cols * (_maccur_lines - 1) * sizeof(chtype));
- scrn_ptr = screen_char_arry + ((_maccur_lines - 1) * _maccur_cols);
- for (i = 0; i < _maccur_cols; i++) /* Clear bottom line. */
- *(scrn_ptr + i) = ' ';
-
- for (i = 0; i < _maccur_lines; i++)
- maccur_draw_text_line(screen_char_arry + i * _maccur_cols,
- _maccur_cols, i, 0);
- cursor_inverted = FALSE;
- }
-
- /********
- **
- ** maccur_noncurse_mode_show_str: Display a string on the screen.
- ** Wrap strings that are too long and expand tabs.
- **
- **
- ********/
-
- static void maccur_noncurse_mode_show_str(
- char *str, /* -R- String to display. */
- int *row_pos_ptr, /* -M- Passed as row to start string, updated to row of end of string. */
- int *col_pos_ptr, /* -M- Passed as column to start string, updated to column of end of string. */
- int *scroll_cnt_ptr, /* -W- Return number of lines up the screen was scrolled. */
- bool show_str_flag, /* -R- TRUE to display string, FALSE to just return cursor position at end of string. */
- bool add_newline_flag, /* -R- True if extra newline should be added after string is displayed. */
- bool clear_to_eos_flag /* -R- True to clear all of screen following displayed string. */
- ) {
- int nchars, char_pos, row_pos, col_pos, i, n_to_show,
- end_col_pos, move_down_flag;
- chtype *scrn_ptr;
- char *out_ptr, *cp;
-
- if (scroll_cnt_ptr != NULL)
- *scroll_cnt_ptr = 0;
- nchars = strlen(str);
- char_pos = 0;
- row_pos = *row_pos_ptr;
- col_pos = *col_pos_ptr;
- out_ptr = str;
-
- while (nchars > 0) /* Loop while there are characters to write out. */
- {
- if (col_pos >= _maccur_cols)
- {
- col_pos = 0;
- row_pos++;
- }
-
- if (show_str_flag && row_pos >= _maccur_lines) /* If writing position is past end of screen, scroll. */
- {
- maccur_noncurse_mode_scroll();
- if (scroll_cnt_ptr != NULL) (*scroll_cnt_ptr)++;
- row_pos = _maccur_lines - 1;
- }
-
- n_to_show = MIN(_maccur_cols - col_pos, nchars); /* Determine how many chars to put in this line: */
- if ((cp = strchr(out_ptr, '\n')) != NULL) /* up to end of line, up to end of string, */
- n_to_show = MIN(n_to_show, cp - out_ptr); /* up to next newline, or up to tab. */
- if ((cp = strchr(out_ptr, '\t')) != NULL)
- n_to_show = MIN(n_to_show, cp - out_ptr);
-
- if (show_str_flag)
- {
- scrn_ptr = screen_char_arry + (row_pos * _maccur_cols) +
- col_pos;
- for (i = 0; i < n_to_show; i++) /* Copy the characters out. */
- *(scrn_ptr + i) = *(out_ptr + i);
- }
- col_pos += n_to_show;
-
- move_down_flag = FALSE;
- if (*(out_ptr + n_to_show) == '\n') /* If newline encountered, blank out rest of line */
- { /* and position to beginning of next. */
- if (show_str_flag)
- {
- scrn_ptr = screen_char_arry + (row_pos * _maccur_cols);
- while (col_pos < _maccur_cols)
- *(scrn_ptr + col_pos++) = ' ';
- }
- n_to_show++; /* Skip over the '\n' */
- move_down_flag = TRUE;
- }
- else if (*(out_ptr + n_to_show) == '\t') /* For a tab, blank up to the next tab stop. */
- {
- end_col_pos = col_pos + (_curses_tab_wid - /* Blank fwd until col_pos becomes multiple of tab wid. */
- col_pos % _curses_tab_wid);
- end_col_pos = MIN(end_col_pos, _maccur_cols); /* But don't wrap over into next line. */
- if (show_str_flag)
- {
- scrn_ptr = screen_char_arry + (row_pos * _maccur_cols);
- while (col_pos < end_col_pos)
- *(scrn_ptr + col_pos++) = ' ';
- }
- col_pos = end_col_pos;
- n_to_show++; /* Skip over the '\t' */
- }
-
- if (show_str_flag)
- maccur_draw_text_line(screen_char_arry + /* Redraw the modified line. */
- row_pos * _maccur_cols,
- _maccur_cols, row_pos, 0);
-
- if (move_down_flag)
- {
- col_pos = 0; /* Move to next line. */
- row_pos++;
- }
-
- if (show_str_flag && row_pos >= _maccur_lines) /* If writing position is past end of screen, scroll. */
- {
- maccur_noncurse_mode_scroll();
- if (scroll_cnt_ptr != NULL) (*scroll_cnt_ptr)++;
- row_pos = _maccur_lines - 1;
- }
-
- out_ptr += n_to_show;
- nchars -= n_to_show;
- }
-
- if (add_newline_flag || clear_to_eos_flag) /* If extra newline is to be added after string output or */
- { /* or screen is to be cleared up to end of screen. */
- if (show_str_flag)
- {
- int last_row, i_rw;
-
- if (clear_to_eos_flag) /* Whether new line or cleareos, will be clearing rest */
- last_row = _maccur_lines; /* of current line and possibly others. */
- else last_row = row_pos + 1;
-
- for (i_rw = row_pos; i_rw < last_row; i_rw++) /* Do next line or a bunch depending on clear_to_eos_flag. */
- {
- scrn_ptr = screen_char_arry + (i_rw * _maccur_cols);
- for (i = (i_rw == row_pos ? col_pos : 0); /* Clear the line. */
- i < _maccur_cols; i++)
- *(scrn_ptr + i) = ' ';
-
- maccur_draw_text_line(screen_char_arry + /* Redraw the modified line. */
- i_rw * _maccur_cols,
- _maccur_cols, i_rw, 0);
- }
- }
-
- if (add_newline_flag) /* If actually echoing a newline. */
- {
- col_pos = 0;
- row_pos++;
- if (show_str_flag && row_pos >= _maccur_lines) /* Scroll of necessary. */
- {
- maccur_noncurse_mode_scroll();
- if (scroll_cnt_ptr != NULL) (*scroll_cnt_ptr)++;
- row_pos = _maccur_lines - 1;
- } /* (this automatically clears the last line of screen). */
- }
- }
-
- *row_pos_ptr = row_pos;
- *col_pos_ptr = col_pos;
- }
-
- /********
- **
- ** maccur_noncurse_mode_getstr: Input a string, echoing input to screen,
- ** allowing editing with left/right arrows, delete key, clear key
- ** (or ctrl-u) to clear input, ctrl-e to move to end of input,
- ** ctrl-d to return EOF. Special single character mode does away
- ** with most special line editing, and returns with the single char (ala getchar).
- **
- ** Returns:
- ** Number of characters in, or EOF if CTRL-D entered.
- **
- **
- ********/
-
- static int maccur_noncurse_mode_getstr(
- char *str, /* -W- Put the string read here. */
- int max_chars, /* -R- Size of above string (or -1 if unknown). */
- int single_char_flag /* -R- True if this is call for a single character. */
- ) {
- int begin_at, nchars, pos, key, c_ascii, cleareos_flag,
- redisplay_flag, disp_pos, disp_row, disp_col, scroll_cnt,
- rtn_val, string_ended_flag, add_newline_flag, save_char;
-
- begin_at = (direct_curs_pos_row * _maccur_cols) + /* Remember initial cursor position. */
- direct_curs_pos_col;
-
- nchars = pos = rtn_val = 0;
- *str = '\0';
- string_ended_flag = FALSE;
- while (!string_ended_flag)
- {
- redisplay_flag = FALSE;
- cleareos_flag = FALSE;
- add_newline_flag = FALSE;
-
- if (typeahead_cnt == 0) /* If need to wait for input... */
- {
- disp_row = begin_at/_maccur_cols;
- disp_col = begin_at % _maccur_cols;
- save_char = *(str + pos);
- *(str + pos) = '\0';
- maccur_noncurse_mode_show_str(str, /* Measure string to determine cursor position at */
- &disp_row, &disp_col, /* input point (there might be tabs). */
- NULL, FALSE, FALSE, FALSE);
- *(str + pos) = save_char;
-
- if (disp_col >= _maccur_cols) /* Move cursor to next line if it is past end of a line. */
- {
- disp_col = 0;
- disp_row++;
- }
-
- if (disp_row >= _maccur_lines) /* Scroll if cursor off screen. */
- {
- maccur_noncurse_mode_scroll();
- disp_row = _maccur_lines - 1;
- begin_at -= _maccur_cols;
- }
-
- maccur_set_cursor(disp_row, disp_col); /* Set cursor to current input position. */
- maccur_event_loop(SET_BIT(MACCUR_RETURN_ON_CHAR_BIT)); /* Get some text. */
- maccur_unflash_cursor();
- }
-
- if (typeahead_cnt > 0) /* There should be at least one keystroke available. */
- {
- typeahead_cnt--;
- if (outchar_indx >= MAX_TYPEAHEAD) outchar_indx = 0;
- c_ascii = (typebuf + outchar_indx)->msg & charCodeMask;
- key = ((typebuf + outchar_indx)->msg & keyCodeMask) >> 8;
- outchar_indx++;
-
- switch (key) /* See if key has special meaning. */
- {
- case 0x7D: /* Up and down arrows (Mac plus and II). */
- case 0x7E: /* All ignored. */
- case 0x4D:
- case 0x48:
- SysBeep(1);
- break;
-
- case 0x7C: /* Right arrow (Mac II). */
- case 0x42: /* (Mac plus). */
- if (pos < nchars)
- pos++;
- else SysBeep(1);
-
- break;
-
- case 0x7B: /* Left arrow (Mac II). */
- case 0x46: /* (Mac plus). */
- if (pos > 0)
- pos--;
- else SysBeep(1);
-
- break;
-
- case 0x33: /* DELETE key. */
- if (pos > 0)
- {
- if (pos < nchars)
- memmove(str + (pos - 1), str + pos, nchars - pos);
- *(str + --nchars) = '\0';
- pos--;
- redisplay_flag = TRUE;
- cleareos_flag = TRUE;
- }
- else SysBeep(1);
-
- break;
-
- case 0x47: /* CLEAR key. */
- if (single_char_flag) SysBeep(1); /* Don't let getchar user think CLEAR means anything. */
- nchars = pos = 0;
- *str = '\0';
- redisplay_flag = TRUE;
- cleareos_flag = TRUE;
- break;
-
- case 0x24: /* RETURN key. */
- case 0x4C: /* ENTER key. */
- if (single_char_flag) /* Single character mode will allow \n as a return value. */
- {
- *str = '\n';
- *(str + 1) = '\0';
- nchars = 1;
- }
- else add_newline_flag = TRUE; /* Don't return newline in string, so set flag to echo it. */
- string_ended_flag = TRUE;
- redisplay_flag = TRUE; /* Redisplay it to echo newline. */
- rtn_val = pos = nchars;
- break;
-
- default:
- if (c_ascii == 4) /* Control-D (return EOF). */
- {
- rtn_val = EOF;
- string_ended_flag = TRUE;
- }
- else if (!single_char_flag && c_ascii == 5) /* Control-E (move to end of input text). */
- {
- pos = nchars;
- }
- else if (!single_char_flag && c_ascii == 21) /* Control-U (same as CLEAR) */
- {
- nchars = pos = 0;
- *str = '\0';
- redisplay_flag = TRUE;
- cleareos_flag = TRUE;
- }
- else /* Get here if its just a regular old ascii value. */
- {
- if (max_chars >= 0 && nchars >= max_chars - 1)
- SysBeep(1);
- else
- {
- if (pos < nchars)
- memmove(str + (pos + 1), str + pos, nchars - pos);
- *(str + pos++) = c_ascii;
- *(str + ++nchars) = '\0';
- redisplay_flag = TRUE;
- }
- }
- break;
- }
-
- if (redisplay_flag) /* If something has happened necesitating a redraw, do it. */
- {
- disp_pos = MAX(0, pos - 1); /* Just redraw from current position on. */
- disp_row = begin_at/_maccur_cols; /* But first measure to find start position. */
- disp_col = begin_at % _maccur_cols;
- save_char = *(str + disp_pos);
- *(str + disp_pos) = '\0';
- maccur_noncurse_mode_show_str(str,
- &disp_row, &disp_col,
- NULL, FALSE, FALSE, FALSE);
- *(str + disp_pos) = save_char;
-
- maccur_noncurse_mode_show_str(str + disp_pos,
- &disp_row, &disp_col,
- &scroll_cnt, TRUE,
- add_newline_flag, cleareos_flag);
- begin_at -= scroll_cnt * _maccur_cols;
- }
-
- if (single_char_flag && nchars > 0 && !string_ended_flag)
- {
- string_ended_flag = TRUE;
- rtn_val = nchars;
- }
- }
- }
-
- direct_curs_pos_row = disp_row; /* Leave cursor where last update put it. */
- direct_curs_pos_col = disp_col;
-
- return rtn_val;
- }
-
- /********
- **
- ** maccur_printf: Equivalent to printf.
- **
- ** Returns:
- ** Results of vsprintf.
- **
- **
- ********/
-
- int maccur_printf(
- char *fmt,
- ...
- ) {
- va_list args;
- int rtn;
-
- if (screen_char_arry == NULL)
- maccur_init();
-
- va_start(args, fmt);
- rtn = vsprintf(_curses_prntw, fmt, args);
- va_end(args);
-
- if (rtn < 0) return rtn;
-
- maccur_noncurse_mode_show_str(_curses_prntw, &direct_curs_pos_row,
- &direct_curs_pos_col, NULL, TRUE,
- FALSE, FALSE);
-
- if (_maccur_io_sleep_dvsr > 0 && ++cpu_share_rot_cnt >= _maccur_io_sleep_dvsr)
- {
- maccur_cpu_share();
- cpu_share_rot_cnt = 0;
- }
-
- return rtn;
- }
-
- /********
- **
- ** maccur_puts: Equivalent to puts.
- **
- ** Returns:
- ** 0 (success).
- **
- **
- ********/
-
- int maccur_puts(
- char *str
- ) {
- if (screen_char_arry == NULL)
- maccur_init();
-
- maccur_noncurse_mode_show_str(str, &direct_curs_pos_row,
- &direct_curs_pos_col, NULL, TRUE,
- TRUE, FALSE);
-
- if (_maccur_io_sleep_dvsr > 0 && ++cpu_share_rot_cnt >= _maccur_io_sleep_dvsr)
- {
- maccur_cpu_share();
- cpu_share_rot_cnt = 0;
- }
-
- return 0;
- }
-
- /********
- **
- ** maccur_putchar: Equivalent to putchar.
- **
- ** Returns:
- ** Character printed.
- **
- **
- ********/
-
- int maccur_putchar(
- char c
- ) {
- char str[2];
-
- if (screen_char_arry == NULL)
- maccur_init();
-
- str[0] = c;
- str[1] = '\0';
-
- maccur_noncurse_mode_show_str(str, &direct_curs_pos_row,
- &direct_curs_pos_col, NULL, TRUE,
- FALSE, FALSE);
-
- if (_maccur_io_sleep_dvsr > 0 && ++cpu_share_rot_cnt >= _maccur_io_sleep_dvsr)
- {
- maccur_cpu_share();
- cpu_share_rot_cnt = 0;
- }
-
- return c;
- }
-
- /********
- **
- ** maccur_scanf: Equivalent to scanf. Uses THINK C's non-portable _vsscanf.
- **
- ** Returns:
- ** Results of _vsscanf.
- **
- **
- ********/
-
- int maccur_scanf(
- char *fmt,
- ...
- ) {
- va_list args;
- int rtn;
-
- if (screen_char_arry == NULL)
- maccur_init();
-
- maccur_noncurse_mode_getstr(_curses_prntw, _curses_prntw_size, FALSE);
-
- va_start(args, fmt);
- rtn = _vsscanf(_curses_prntw, fmt, args);
- va_end(args);
-
- return rtn;
- }
-
- /********
- **
- ** maccur_gets: Equivalent to gets.
- **
- ** Returns:
- ** Pointer to string argument (success).
- **
- **
- ********/
-
- char *maccur_gets(
- char *str
- ) {
-
- if (screen_char_arry == NULL)
- maccur_init();
-
- if (maccur_noncurse_mode_getstr(str, -1, FALSE) == EOF)
- return NULL;
-
- return str;
- }
-
- /********
- **
- ** maccur_getchar: Equivalent to getchar.
- **
- ** Returns:
- ** Character read or EOF.
- **
- **
- ********/
-
- int maccur_getchar(void)
- {
- char str[2];
- int rtn;
-
- if (screen_char_arry == NULL)
- maccur_init();
-
- if (maccur_noncurse_mode_getstr(str, 2, TRUE) == EOF)
- rtn = EOF;
- else
- rtn = str[0];
-
- return rtn;
- }
-